package com.woniu.order.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Snowflake;
import com.alipay.api.domain.Goods;
import com.alipay.api.domain.OrderGoodsDTO;
import com.alipay.api.internal.util.AlipaySignature;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.woniu.config.AlipayConfiguration;
import com.woniu.exception.userexp.YogaException;
import com.woniu.model.Result;
import com.woniu.order.Param.OrderByShoppingCarParam;
import com.woniu.order.Param.OrderPayParam;
import com.woniu.order.Param.PageParam;
import com.woniu.model.PagePayParam;
import com.woniu.order.client.GoodsDto;
import com.woniu.order.client.ProductClient;
import com.woniu.order.dao.GoodsItemDao;
import com.woniu.order.dto.GoodsOrderDto;
import com.woniu.order.model.GoodsItem;
import com.woniu.order.model.GoodsOrder;
import com.woniu.order.dao.GoodsOrderDao;
import com.woniu.order.service.GoodsOrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniu.util.AlipayUtil;
import com.woniu.util.RedisKeyUtil;
import com.woniu.util.RedisUtil;
import com.woniu.util.StateUtil;
import io.swagger.annotations.ApiOperation;
import net.sf.jsqlparser.statement.create.table.Index;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 杜岷芫
 * @since 2024年07月12日
 */
@Service
public class GoodsOrderServiceImpl extends ServiceImpl<GoodsOrderDao, GoodsOrder> implements GoodsOrderService {
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private RedissonClient redissonClient;
    @Resource
    private ProductClient productClient;
    @Resource
    private GoodsItemDao goodsItemDao;

    @Resource
    private RabbitTemplate rabbitTemplate;
    @Resource
    private AlipayUtil alipayUtil;
    @Resource
    private AlipayConfiguration alipayConfiguration;
    @Resource
    private GoodsOrderDao goodsOrderDao;

//用户查询自己的订单
    @Override
    @ApiOperation(value = "查询商品")
    public Page<GoodsOrder> selsectOrders(PageParam param, int userId) throws YogaException {
        QueryWrapper<GoodsOrder> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id",userId);
        Page<GoodsOrder> page = new Page<>(param.getPageNum(), param.getPageSize());
        baseMapper.selectPage(page,wrapper);
        return page;
    }

    @Override
    public Object pay(OrderPayParam orderPayParam) throws Exception {
        //1.检验传进来的参数是否正确
        QueryWrapper<GoodsOrder> wrapper = new QueryWrapper<>();
        wrapper.eq("order_num",orderPayParam.getOrderNum());
        GoodsOrder goodsOrder = goodsOrderDao.selectOne(wrapper);
        if (goodsOrder == null ||!Objects.equals(goodsOrder.getOrderNum(), orderPayParam.getOrderNum())){
            throw new YogaException(500,"订单不存在");
        }
        if (!Objects.equals(goodsOrder.getOrderState(), StateUtil.GOODS_ORDER_STATE_DISABLED)){
            throw new YogaException(500,"订单状态异常");
        }
        //2.组装参数
        PagePayParam payParam = new PagePayParam(); // 使用正确包下的 PagePayParam
        payParam.setBody("yogo订单支付");
        payParam.setMoney(goodsOrder.getPrice().doubleValue());
        payParam.setNotifyUrl("http://localhost:8081/order/goodsOrder/notify");
        payParam.setReturnUrl("http://localhost:8081/order/goodsOrder/notify");
        payParam.setOrderId(goodsOrder.getOrderNum());
        payParam.setSubject("yoga");
        //取出数据库订单的下单时间
        long expireTime = Date.from(LocalDateTime.parse(goodsOrder.getCreateTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")).plusMinutes(25).atZone(ZoneId.systemDefault()).toInstant()).getTime();
        long now = new Date().getTime();
        int minute = (int)((expireTime - now)/1000/60);
        if (minute<1){
            throw new YogaException(500,"订单超时");
        }
        Date date = new Date(expireTime);
        String expire = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
        payParam.setTimeExpire(expire);//可支付的时间
        //调用支付宝工具类
        return alipayUtil.pagePay(payParam);
    }

   //   给支付宝回调的接口

    @Override
    public void payNotify(Map<String, String> map) throws Exception {
        //第一步验签
        boolean signVerified = AlipaySignature.rsaCheckV1(map, alipayConfiguration.getAlipayPublicKey(), "utf-8", "RSA2");
        if (signVerified) {
            //验签成功


            String status = map.get("trade_status");

            if ("TRADE_SUCCESS".equals(status)){
                String orderNum = map.get("out_trade_no");
                //支付成功
                //修改订单状态为支付
                QueryWrapper<GoodsOrder> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("order_num",orderNum);
                GoodsOrder GoodsOrder = goodsItemDao.selectOne(queryWrapper);

                if (Objects.equals(GoodsOrder.getOrderState(), StateUtil.GOODS_ORDER_STATE_DISABLED)) {
                    //如果订单状态是未支付才进下一步操作
                    GoodsOrder.setOrderState(StateUtil.GOODS_ORDER_STATE_START);
                    String payTimeStr = map.get("send_pay_date");
                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                    LocalDateTime parse = LocalDateTime.parse(payTimeStr, formatter);
                    GoodsOrder.setPayTime(String.valueOf(parse));
                    //修改冻结量
                    List<GoodsItem> list = goodsItemDao.selectList(new QueryWrapper<GoodsItem>().eq("order_num", orderNum));
                    for (GoodsItem item :list){
                        Result<GoodsDto> GoodsDtoResult = productClient.byId(item.getGoodsId());
                        GoodsDto data = GoodsDtoResult.getData();
                        Goods goods = BeanUtil.toBean(data, Goods.class);
                        productClient.updateByIdGoods(goods);
                    }
                    goodsItemDao.updateById(GoodsOrder);
                }
            }
        }
    }
    // 分页查询

    @Override
    public Page<GoodsOrder> loadPageGoodsOrder(PageParam param) throws YogaException {
        Page<GoodsOrder> page = new Page<>(param.getPageNum(), param.getPageSize());

        QueryWrapper<GoodsOrder> wrapper = new QueryWrapper<>();

        baseMapper.selectPage(page,wrapper);

        return page;
    }

    @Override
    public GoodsOrderDto orderByShoppingCar(OrderByShoppingCarParam param) throws Exception {
        //1.对商品Id进行排序
        Collections.sort(param.getGoodsIdList());//对商品Id进行升序排列
        //Collections.sort() 方法用于对集合进行排序，它接受一个列表作为参数，并按照元素的自然顺序对列表进行排序
        System.out.println(param.getGoodsIdList()+"===================");
        //2查询商品的信息
        ArrayList<GoodsItem> orderItemsList = new ArrayList<>();
        BigDecimal total = new BigDecimal(0);
        for (Integer goodsId : param.getGoodsIdList()) {
            if (redisUtil.zscore(RedisKeyUtil.userShopping(param.getUserId()), goodsId + "") == null) {
                throw new YogaException(500, "商品不存在");
            }
            //取出购物车商品信息
            Map<Object, Object> map = redisUtil.hgetall(RedisKeyUtil.shoppingInfo(param.getUserId(), goodsId));


            //redisUtil.hgetall查询一个hash数据
            GoodsItem goodsItem = new GoodsItem();

            goodsItem.setGoodsId(Integer.parseInt(map.get("GoodsId").toString()));
            //goodsItem.setGoodsNum(Integer.parseInt(map.get("GoodsNum").toString()));
            goodsItem.setGoodsPrice(new BigDecimal(map.get("GoodsPrice").toString()));
            goodsItem.setGoodsNum(Integer.parseInt(map.get("GoodsNumber").toString()));


            orderItemsList.add(goodsItem);
        }
        //创建多个单锁
        RLock[] lockArray = new RLock[param.getGoodsIdList().size()];
        int index = 0;
        for (Integer bookId : param.getGoodsIdList()) {
            RLock locks = redissonClient.getFairLock(RedisKeyUtil.lockOrderGoodsId(bookId));
            lockArray[index++] = locks;
        }
        //使用数组创建多资源锁
        RLock lock = redissonClient.getMultiLock(lockArray);
        try {
            //加锁
            if (lock.tryLock(20, TimeUnit.SECONDS)) {

                //循环商品详情查询数据库
                for (GoodsItem item : orderItemsList) {
                    Result<GoodsDto> GoodsDtoResult = productClient.byId(item.getGoodsId());
                    GoodsDto dto = GoodsDtoResult.getData();
                    if (dto == null) {
                        throw new YogaException(500, item.getGoodsId() + "该商品不存在，请删除后重新下单");
                    }
                    if (dto.getGoodsNum() < item.getGoodsNum()) {
                        throw new YogaException(500, item.getGoodsNum() + "数量不足，请修改数量");
                    }
                    BigDecimal number = new BigDecimal(item.getGoodsNum());
                    BigDecimal price = new BigDecimal(item.getGoodsPrice().toString());
                    BigDecimal money = price.multiply(number);
                    total = total.add(money);
                }
                //下单操作
                GoodsOrder yGoodsOrder = BeanUtil.toBean(param, GoodsOrder.class);
                //使用雪花生成订单号
                String orderNum = new Snowflake(1, 1).nextIdStr();
                //组装参数
                yGoodsOrder.setOrderNum(orderNum);//订单号
                yGoodsOrder.setCreateTime(String.valueOf(LocalDateTime.now()));//订单生成时间
                yGoodsOrder.setPrice(total);//订单价格
                yGoodsOrder.setOrderState(StateUtil.GOODS_ORDER_STATE_DISABLED);//刚生成订单，给订单状态一个未支付的状态
                //新增订单信息
                goodsOrderDao.insert(yGoodsOrder);

                //循环新增订单详细信息
                for (GoodsItem item:orderItemsList){
                    item.setOrderNum(orderNum);
                    goodsItemDao.insert(item);
                }
                try {
                    //删除redis中的购物车信息
                    for(Integer goodsId:param.getGoodsIdList()){
                        redisUtil.zrem(RedisKeyUtil.userShopping(param.getUserId()),goodsId+"");
                        redisUtil.delete(RedisKeyUtil.shoppingInfo(param.getUserId(),goodsId));
                    }
                }catch (YogaException e){
                    e.printStackTrace();
                    //日志记录
                }
                //将订单编号发送到延迟队列中
                GoodsOrderDto dto = BeanUtil.toBean(yGoodsOrder, GoodsOrderDto.class);
                dto.setMinutes(15);
                rabbitTemplate.convertAndSend("ordernum_delay_queue",orderNum);
                return dto;
            } else {
                throw new Exception("业务繁忙");
            }
        } finally {
            lock.unlock();//释放锁
        }
    }

    @Override
    public GoodsOrder getOneId(String orderNum) {
        QueryWrapper<GoodsOrder> wrapper = new QueryWrapper<>();
        wrapper.eq("order_num",orderNum);
        GoodsOrder yGoodsOrder = goodsOrderDao.selectOne(wrapper);
        if (yGoodsOrder==null){
            throw new YogaException(500,"订单不存在");
        }
        return yGoodsOrder;
    }

    @Override
    public void updateByIdGoodsOrder(GoodsOrder GoodsOrder) {
        goodsOrderDao.updateById(GoodsOrder);
    }


}
